package mya.mes.mdc.logic.tag;


import mya.mes.mdc.model.plc.PlcTagDef;
import mya.mes.mdc.share.plc.TagPrefix;
import mya.mes.mdc.share.vo.plc.PlcTagDefArray;
import mya.mes.mdc.share.vo.plc.PlcTagVo;

import java.util.List;

abstract class AbstractPlcTagCache<T extends PlcTagDefArray> {

    protected T[] AIArray;
    protected T[] DIArray;
    protected T[] STArray;


    public T getAI(Integer tagIndex) {
        return get(AIArray, tagIndex);
    }


    public T getDI(Integer tagIndex) {
        return get(DIArray, tagIndex);
    }


    public T getST(Integer tagIndex) {
        return get(STArray, tagIndex);
    }

    public T get(PlcTagVo vo) {
        return get(vo.dataType, vo.tagIndex);
    }

    public T get(String prefix, Integer tagIndex) {
        if (TagPrefix.AI.equals(prefix)) {
            return get(AIArray, tagIndex);
        }
        if (TagPrefix.DI.equals(prefix)) {
            return get(DIArray, tagIndex);
        }
        if (TagPrefix.ST.equals(prefix)) {
            return get(STArray, tagIndex);
        }
        return null;
    }


    private T get(T[] array, Integer tagIndex) {
        if (array == null) {
            return null;
        }

        if (tagIndex == null) {
            return null;
        }

        if (tagIndex < 0 || tagIndex >= array.length) {
            return null;
        }

        return array[tagIndex];

    }


    public synchronized <M extends PlcTagDef> void update(List<M> tagDefList) {
        int aiMax = 0;
        int diMax = 0;
        int stMax = 0;

        for (M tagDef : tagDefList) {
            if (TagPrefix.AI.equals(tagDef.getTagPrefix())) {
                if (tagDef.getTagIndex() > aiMax) {
                    aiMax = tagDef.getTagIndex();
                }
                continue;
            }

            if (TagPrefix.DI.equals(tagDef.getTagPrefix())) {
                if (tagDef.getTagIndex() > diMax) {
                    diMax = tagDef.getTagIndex();
                }
                continue;
            }


            if (TagPrefix.ST.equals(tagDef.getTagPrefix())) {
                if (tagDef.getTagIndex() > stMax) {
                    stMax = tagDef.getTagIndex();
                }
                continue;
            }
        }

        int aiLen = aiMax > 0 ? (aiMax + 1) : 0;
        int diLen = diMax > 0 ? (diMax + 1) : 0;
        int stLen = stMax > 0 ? (stMax + 1) : 0;

        createArray(aiLen, diLen, stLen);

        for (M tagDef : tagDefList) {
            if (TagPrefix.AI.equals(tagDef.getTagPrefix())) {
                T tmp = getOrCreate(AIArray, tagDef.getTagIndex());
                tmp.set(tagDef);
                continue;
            }

            if (TagPrefix.DI.equals(tagDef.getTagPrefix())) {
                T tmp = getOrCreate(DIArray, tagDef.getTagIndex());
                tmp.set(tagDef);
                continue;
            }


            if (TagPrefix.ST.equals(tagDef.getTagPrefix())) {
                T tmp = getOrCreate(STArray, tagDef.getTagIndex());
                tmp.set(tagDef);
                continue;
            }
        }
    }


    private T getOrCreate(T[] array, Integer tagIndex) {

        if(tagIndex >= array.length) {

        }
        if (array[tagIndex] == null) {
            array[tagIndex] = create();
        }

        return array[tagIndex];
    }

    protected abstract void createArray(int aiLen, int diLen, int stLen);


    protected abstract T create();
}
